package com.mobike.android.os

import android.os.Handler
import android.os.Looper
import com.android.basic.androidApp
import pushtest.mobike.com.basic_android.BuildConfig


/**
 * this is declared private, because we won't want anyone call its cancel methods
 */
val __mainThreadHandler = Handler(Looper.getMainLooper())

fun isUiThread() = Looper.getMainLooper() == Looper.myLooper()

fun assertUiThread() {
  val exc = IllegalStateException("Should be on main thread")
  if (Looper.getMainLooper() !== Looper.myLooper()) {
    if (BuildConfig.DEBUG) {
      throw exc
    } else {
      androidApp.printError(exc)
    }
  }
}

fun runOnUiThread(r: () -> Unit) {
  if (Looper.getMainLooper() == Looper.myLooper()) {
    r.invoke()
  } else {
    __mainThreadHandler.post(r)
  }
}

fun runOnUiThread(r: Runnable) {
  if (Looper.getMainLooper() == Looper.myLooper()) {
    r.run()
  } else {
    __mainThreadHandler.post(r)
  }
}

fun postOnUiThread(r: Runnable) = postOnUiThread(r, 0)
inline fun postOnUiThread(crossinline r: () -> Unit) = postOnUiThread(Runnable { r() }, 0)

/**
 * @filter when to end checking
 * @action what to do when checking ended, the parameter is if this action is forced at the end or it is actually meet
 */
fun repeatedCheckOnUiThread(
  filter: () -> Boolean, action: (Boolean) -> Unit, interval: Long,
  forceDoTime: Long
) {
  if (filter.invoke()) {
    action.invoke(false)
    return
  }
  postOnUiThread(object : Runnable {
    var remaining = forceDoTime
    override fun run() {
      remaining -= interval
      if (remaining > 0) {
        if (filter.invoke()) {
          action.invoke(false)
        } else {
          postOnUiThread(this, interval)
        }
      } else {
        action.invoke(true)
      }
    }
  }, interval)
}

fun postOnUiThread(r: Runnable, delay: Long) = __mainThreadHandler.postDelayed(r, delay)

inline fun postOnUiThread(crossinline r: () -> Unit, delay: Long) = __mainThreadHandler.postDelayed(
  { r() }, delay
)

fun removeUiThreadCallbacks(r: Runnable) = __mainThreadHandler.removeCallbacks(r)
